package decorator.io;

import java.io.*;

/**
 * FilterInputStream为InputStream的装饰器类
 * <p>
 * InputStream的所有子类中其余的都是定义数据源如FileInputStream,StringBufferInputStream,PipedInputStream，
 * 即数据的获取源头，而FilterInputStream却是一个装饰器，它实现了InputStream的所有接口，但是他的子类
 * 定义了几种数据转换，对数据操作的额外方法如BufferedInputStream，LineNumberInputStream，
 * 这样使InputStream更加灵活，且不用定义很多子类(假设需要读取每行文件的每行数据，就不需要定
 * 义一个FileLineNumberInputStream类，如果直接在FileInputStream中定义一个getLineNumber等方法，
 * 这样有的时候用不到显得很low） ，只需要通过装饰器构造一个就好了（new LineNumberInputStream(new  FileInputStream())）
 * 这样就可以动态扩展更多功能了
 * <p>
 * <p>
 * //先调用generator方法生成test.txt文件
 * //然后调用读取文件行号
 * Created by yangliwei on 2018/3/20.
 */
public class FilterInputStreamDemo {
    private static final String CLASSPATH;
    private static final String FILEPATH;

    static {
        CLASSPATH = FilterInputStreamDemo.class.getResource("").getPath();
        FILEPATH = CLASSPATH + File.separator + "test.txt";
    }


    public static void main(String[] args) {
        generateTestFile();
        //InputStream in = new LineNumberInputStream(new FileInputStream());
        LineNumberInputStream in = null;
        try {
            in = new LineNumberInputStream(new FileInputStream(FILEPATH));
            byte[] sb = new byte[1024];

            //当前所在字符的行号
            while(in.read(sb)!=-1){
                System.out.println(in.getLineNumber());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null)
                    in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //生成测试文件
    private static void generateTestFile() {

        BufferedOutputStream out = null;
        try {
            out = new BufferedOutputStream(new FileOutputStream(new File(FILEPATH)));
            byte[] b = new byte[1024];

            for (int i = 0; i < 100; i++) {
                StringBuilder sb = new StringBuilder();
                sb.append(i + " ");
                for (int j = 0; j < 100; j++) {
                    sb.append((char) ('a' + i));
                }
                sb.append("\n");
                b = sb.toString().getBytes();
                out.write(b);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    //这个close需要注意，因为他是BufferedOutputStream对象，
                    // 他先调用父类因为他是FilterOutputStream对象里面的close()，然后在调用自己的fulsh()，
                    //最后调用它持有的FileOutputStream对象的close方法
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
